﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

/// <summary>
/// Page for adding a new model to the models list and the logic behind it
/// </summary>
public partial class Admin_Asp_add_model : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {      
        if (!LoginHandler.IsLoggedIn(Session))
        {
            Response.Redirect(Paths.admin_index);
        }

        if (Request.QueryString[Strings.Query_Control] != null)
        {
            string f_control = Request.QueryString[Strings.Query_Control];

            if (f_control == Strings.Query_Control_Shader)
            {                
                x_shaderSelection.Visible = true;
            }
            else if (f_control == Strings.Query_Control_Thumbnail)
            {
                x_thumbnailSelection.Visible = true;
            }
            else if (f_control == Strings.Query_Control_Texture)
            {
                x_textureSelection.Visible = true;
            }
        }       
        //TODO: fix this so it works later!
        //If coming from some other page, remove the session variables
        /*if (!IsPostBack )
        {
            Session.Remove(Strings.Session_Name);
            Session.Remove(Strings.Session_OutputPath);
            Session.Remove(Strings.Session_Thumbnail);
            Session.Remove(Strings.Session_TextureChanges);
            Session.Remove(Strings.Session_Shaders);

            Response.Write("Was not a postback");
        }*/

        //Name
        SetTextbox(Strings.Session_Name, x_name);

        //Input
        SetInputFile(Strings.Session_InputPath, x_inputFile, x_inputLabel, x_inputPanel);

        //Output Path
        SetTextbox(Strings.Session_OutputPath, x_outputPath);               

        //Thumbnail
        string f_thumbnailPath = "";
        if (Session[Strings.Session_Thumbnail] != null)
        {
            f_thumbnailPath = Session[Strings.Session_Thumbnail] as string;
        }
        SetImagefield(x_thumbnail_label, x_thumbnail_image, f_thumbnailPath, Strings.error_selection_noThumbnail);
        
        //Shader
        //If there is no data about shaders in the session then add it
        if (Session[Strings.Session_Shaders] == null)
        {
            List<string> f_tempShaderList = new List<string>();                     
            Session[Strings.Session_Shaders] = f_tempShaderList;
        }

        List<string> f_shadersList = Session[Strings.Session_Shaders] as List<String>;
        x_shaders.Text = "";
        
        foreach (string shader in f_shadersList)
        {
            x_shaders.Text += shader + " ";
        }
        if (x_shaders.Text == "")
        {
            x_shaders.Text = Strings.error_selection_noShader;
        }

        //Textures
        string f_diffuseMap = "", f_normalMap = "";

        //Function to see if the texture for a particular kind exists
        if (Session[Strings.Session_TextureChanges] != null)
        {
            Dictionary<Texture.Type, string> f_textures = Session[Strings.Session_TextureChanges] as Dictionary<Texture.Type, string>;

            if (f_textures.ContainsKey(Texture.Type.diffuse))
            {                
                f_diffuseMap = f_textures[Texture.Type.diffuse];
            }

            if (f_textures.ContainsKey(Texture.Type.normal))
            {                
                f_normalMap = f_textures[Texture.Type.normal];
            }            
        }        

        //Diffuse
        SetImagefield(x_diffuseLabel, x_diffuseImage, f_diffuseMap, Strings.error_selection_noDiffuse);
        //Normal
        SetImagefield(x_normalLabel, x_normalImage, f_normalMap, Strings.error_selection_noNormal);

        //Check if converter is running
        if (Session[Strings.Session_Converter_Started] != null && (bool)Session[Strings.Session_Converter_Started])
        {
            //If it's running then show the ConverterStatus UserControl
        }

    }

    protected void NameChanged(object sender, EventArgs e)
    {
        Session[Strings.Session_Name] = x_name.Text;        
    }

    protected void OutputChanged(object sender, EventArgs e)
    {
        Session[Strings.Session_OutputPath] = x_outputPath.Text;
    }

    protected void ThumbnailChange(object sender, EventArgs e)
    {
        ShowThumbnailSelection();
    }

    protected void ShadersChange(object sender, EventArgs e)
    {
        ShowShadersSelection();
    }

    protected void DiffuseChange(object sender, EventArgs e)
    {
        Session[Strings.Session_CurrentTextureChange] = Texture.Type.diffuse;
        ShowTextureSelection();   
    }

    protected void NormalChange(object sender, EventArgs e)
    {
        Session[Strings.Session_CurrentTextureChange] = Texture.Type.normal;
        ShowTextureSelection();    
    }

    private void ShowThumbnailSelection()
    {
        ShowSelection(true, false, false, Strings.Query_Control_Thumbnail);        
    }

    private void ShowShadersSelection()
    {
        ShowSelection(false, false, true, Strings.Query_Control_Shader);       
    }

    private void ShowTextureSelection()
    {
        ShowSelection(false, true, false, Strings.Query_Control_Texture);
    }

    private void ShowSelection(bool a_thumbnail, bool a_texture, bool a_shader, string a_controlName)
    {
        x_thumbnailSelection.Visible = a_thumbnail;
        x_textureSelection.Visible = a_texture;
        x_shaderSelection.Visible = a_shader;

        string f_query = "?" + Strings.Query_Control + "=" + a_controlName;
        Server.Transfer(Request.Path + f_query);
    }

    private void ShowConverterStatus()
    {

    }

    /// <summary>
    /// Tries to add the model based on user data
    /// </summary>    
    protected void TryToAdd(object sender, EventArgs e)
    {
        /*  Table of Contents:
         *  1. Check if inputFile has file
         *  2. Check extension of inputFile
         *      2.1 if extension requires converter then check if converter is running
         *  3. Set output path
         *      3.1. if overwrite checkbox is false, then add some text!
         *  4. Create the modelitem
         *  5. Validate the item
         *      5.1. ModelItemHandler.AddItem function to add & convert it
        */
        //1. Check if inputfile has a file
        if (!x_inputFile.HasFile)
        {
            SetError(Strings.error_addmodel_noInputfile);
            return;
        }

        //2. Check extension of inputFile
        string f_extension;
        bool f_needsConverter = false;

        if (x_inputFile.FileName.EndsWith(".fbx") )
        {
            f_needsConverter = true;           
            f_extension = ".json";
        }
        else if (x_inputFile.FileName.EndsWith(".obj"))
        {
            f_extension = ".obj";
        }
        else
        {
            SetError(" Model file is not a fbx or obj");
            return;
        }

        //2.1 if extension requires converter then check if converter is running
        if (f_needsConverter)
        {
            ShowConverterStatus();

            //Check if converter has started
            if (ProgramHandler.m_converterStarted || (Session[Strings.Session_Converter_Started] != null && (bool)Session[Strings.Session_Converter_Started]))
            {
                //If converter has started
                SetError("boo");
                return;
            }
        }        
        
        //If user wrote the correct extension then don't append an extra so it'd be .obj.obj e.t.c.
        if (x_outputPath.Text.EndsWith(f_extension))
        {
            f_extension = "";
        }

        //3. Set output path
        string f_outputPath = Paths.ModelsFolder_relative + x_outputPath.Text + f_extension;

        //3.1. if overwrite checkbox is false, then add some text!        
        if (!x_outputOverwrite.Checked)
        {
            int n = 1;
            //The text value from x_outputPath before it adds the _n value, if it didn't save the original value but just appended _n it'd be name_n_2n_3n_4n...
            string f_oldOutputValue = x_outputPath.Text;
            
            //If there would be ~2^32 same name.. then this would not work
            while(true)
            {
                if (System.IO.File.Exists(Paths.serverRoot + f_outputPath))
                {
                    x_outputPath.Text = f_oldOutputValue + "_" + n.ToString();
                    //Set new sessin value so it's persistent
                    Session[Strings.Session_OutputPath] = x_outputPath.Text;
                    //Set a new output path to test
                    f_outputPath = Paths.ModelsFolder_relative + x_outputPath.Text + f_extension;
                    n++;
                    //If it did it 2^32 times... just to not eternal loop it! ^_^
                    if (n == 0)
                    {
                        return;
                    }
                }
                else
                {
                    break;
                }
            }          
        }
        //4. Create the model item
        ModelItem f_item = new ModelItem();        

        f_item.EditName(x_name.Text);
        f_item.EditPath(f_outputPath);
        f_item.EditThumbnailPath(x_thumbnail_label.Text);
        
        //Shaders
        List<string> f_shadersList = Session[Strings.Session_Shaders] as List<String>;
        f_item.EditShaders(f_shadersList);

        //Diffuse
        if (x_diffuseLabel.Text != Strings.error_selection_noDiffuse)
        {
            f_item.EditTexture(Texture.Type.diffuse, x_diffuseLabel.Text);
        }       
        //Normal
        if (x_normalLabel.Text != Strings.error_selection_noNormal)
        {
            f_item.EditTexture(Texture.Type.normal, x_normalLabel.Text);
        }

        //5. Validate the item
        if (ValidatorFactory.StrictValidation(f_item))
        {             
            //Add the modelitem to the models.txt and convert to a fileformat if needed
            if (ModelItemHandler.AddModelItem(f_item, f_outputPath, x_inputFile, Session))
            {               
            }
            else
            {
                SetError(Strings.error_addmodel_failedAdding);
            }
        }
        else
        {
            SetError(ValidatorFactory.GetErrorMsg() );            
        }
        
    }

    private void SetError(string a_msg)
    {
        x_errorMsg.Visible = true;
        x_errorMsg.Text = a_msg;
    }
    //Functions to reduce Page_Load code

    private void SetTextbox(string a_sessionName, TextBox a_textbox)
    {
        if (Session[a_sessionName] != null)
        {
            string f_text = Session[a_sessionName] as string;
            if (a_textbox.Text == "")
            {
                a_textbox.Text = f_text;
            }
            else
            {
                Session[a_sessionName] = a_textbox.Text;
            }

            a_textbox.Text = Session[a_sessionName] as string;
        }      
    }

    private void SetInputFile(string a_sessionName, FileUpload a_inputFile, Label a_label, Panel a_panel)
    {
        if (a_inputFile.HasFile)
        {
            Session[a_sessionName] = a_inputFile;
        }
        else
        {
            if (Session[Strings.Session_InputPath] != null)
            {
                a_inputFile = Session[a_sessionName] as FileUpload;
                a_label.Text = a_inputFile.FileName;
                a_panel.Visible = true;
            }
        }
    }

    private void SetImagefield(Label a_imageLabel, Image a_image ,string a_imagePath, string a_noImage)
    {
        if (a_imagePath == "")
        {
            a_imageLabel.Text = a_noImage;
            a_image.Visible = false;
        }
        else
        {
            a_imageLabel.Text = a_imagePath;
            a_image.ImageUrl = "~/" + a_imagePath;
        }        
    }
}